import axios, { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from 'axios'
import toast from 'react-hot-toast'

// 创建axios实例
export const apiClient: AxiosInstance = axios.create({
  baseURL: '/api/v1',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json',
  },
})

// 请求拦截器
apiClient.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // 自动注入 Authorization 头
    try {
      const authData = localStorage.getItem('auth-storage')
      if (authData) {
        const parsed = JSON.parse(authData)
        const accessToken = parsed.state?.tokens?.accessToken
        if (accessToken) {
          config.headers = config.headers || {}
          config.headers['Authorization'] = `Bearer ${accessToken}`
        }
      }
    } catch {
      // 忽略本地存储解析错误
    }
    return config
  },
  (error) => {
    return Promise.reject(error)
  }
)

// 响应拦截器
apiClient.interceptors.response.use(
  (response: AxiosResponse) => {
    return response
  },
  async (error) => {
    const originalRequest = error.config

    // 处理401未授权错误
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true

      try {
        // 尝试刷新token
        const authData = localStorage.getItem('auth-storage')
        if (authData) {
          const parsed = JSON.parse(authData)
          const refreshToken = parsed.state?.tokens?.refreshToken

          if (refreshToken) {
            const response = await axios.post('/api/v1/auth/refresh', {
              refreshToken,
            })

            const { accessToken } = response.data.tokens
            
            // 更新存储的token
            parsed.state.tokens.accessToken = accessToken
            localStorage.setItem('auth-storage', JSON.stringify(parsed))
            
            // 更新请求头
            apiClient.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`
            originalRequest.headers['Authorization'] = `Bearer ${accessToken}`

            // 重试原始请求
            return apiClient(originalRequest)
          }
        }
      } catch (refreshError) {
        // 刷新失败时，仅当原请求本身带有鉴权头才清除并跳转登录
        const hadAuthHeader = !!(originalRequest?.headers && originalRequest.headers['Authorization'])
        if (hadAuthHeader) {
          try {
            // 动态导入以避免与 authStore 的静态循环依赖
            const mod = await import('@/stores/authStore')
            // 同步清空内存中的登录态，防止 PublicRoute 误判已登录
            mod.useAuthStore.getState().logout()
          } catch {
            // 兜底：即便导入失败也要清理本地存储与全局头
            localStorage.removeItem('auth-storage')
            delete apiClient.defaults.headers.common['Authorization']
          }

          // 最后进行硬跳转，替换历史，避免返回键回到失效页
          if (window.location.pathname !== '/login') {
            window.location.replace('/login')
          }
        }
        return Promise.reject(refreshError)
      }
    }

    // 处理其他错误
    const message = error.response?.data?.message || error.message || '请求失败'
    
    // 根据状态码显示不同的错误信息
    switch (error.response?.status) {
      case 400:
        toast.error('请求参数错误')
        break
      case 403:
        toast.error('没有权限访问')
        break
      case 404:
        toast.error('请求的资源不存在')
        break
      case 422:
        toast.error('数据验证失败')
        break
      case 429:
        toast.error('请求过于频繁，请稍后再试')
        break
      case 500:
        toast.error('服务器内部错误')
        break
      case 502:
      case 503:
      case 504:
        toast.error('服务暂时不可用，请稍后再试')
        break
      default:
        if (error.code === 'NETWORK_ERROR' || error.code === 'ECONNABORTED') {
          toast.error('网络连接失败，请检查网络')
        } else if (!error.response) {
          toast.error('网络错误，请检查连接')
        } else {
          toast.error(message)
        }
    }

    return Promise.reject(error)
  }
)

// 导出常用的HTTP方法
export const api = {
  get: <T = any>(url: string, config?: any) => 
    apiClient.get<T>(url, config),
  
  post: <T = any>(url: string, data?: any, config?: any) => 
    apiClient.post<T>(url, data, config),
  
  put: <T = any>(url: string, data?: any, config?: any) => 
    apiClient.put<T>(url, data, config),
  
  patch: <T = any>(url: string, data?: any, config?: any) => 
    apiClient.patch<T>(url, data, config),
  
  delete: <T = any>(url: string, config?: any) => 
    apiClient.delete<T>(url, config),
}

export default apiClient